package com.atguigu.myRule;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

import java.util.List;

/**
 * @Auther:
 * @Description:
 * @Date: 2019/11/21 16:49
 */
public class RandomRule_ZGQ extends AbstractLoadBalancerRule {
//    Random rand;
//    public RandomRule_ZGQ(){
//        rand = new Random();
//    }

    //当total = 5以后，我们指针才能往下走
    // 当前对外提供服务的服务器地址
    //total 需要中心置为零，但是一惊道到过一个5次，我们的index = 1

    private int total = 0;      // 总共被调用的次数，目前要求每台被调用五次
    private int currentIndex = 0; // 当前提供服务的机器号

    public void initWithNiwsConfig(IClientConfig iClientConfig) {
    }

    public Server choose(Object o) {
        return choose(getLoadBalancer(), o);
    }

    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }
        Server server = null;
        while (server == null) {
            //判断当前线程是否中断
            if (Thread.interrupted()) return null;
            // 获取当前正常服务的实例列表
            List<Server> upList = lb.getReachableServers();
            // 获取所有的服务
            List<Server> allServers = lb.getAllServers();
            int serversCount = allServers.size();
            if (serversCount == 0) return null;

//            int index = rand.nextInt(serversCount);
//            server = upList.get(index);
            if (total < 5) {
                server = upList.get(currentIndex);
                total++;
            } else {
                total = 0;
                currentIndex++;
                if (currentIndex >= upList.size()) {
                    currentIndex = 0;
                }
            }
            if (server == null) {
                // yield 即 “谦让”，也是 Thread 类的方法。它让掉当前线程 CPU 的时间片，使正在运行中的线程重新变成就绪状态，并重新竞争 CPU 的调度权。它可能会获取到，也有可能被其他线程获取到。
                Thread.yield();
                continue;
            }
            /**
             方法isAlive()的功能是判断当前的线程是否处于活动状态。什么是活动状态呢？
             活动状态就是线程已经启动且尚未终止。线程处于正在运行或准备开始运行的状态，
             就认为线程是“存活”的。
             */
            if (server.isAlive()) {
                return server;
            }
            server = null;
            Thread.yield();
        }
        return server;
    }

}
